package com.gitee.wsl.compose.ui.richtext

import androidx.compose.runtime.MutableState
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.style.ResolvedTextDirection
import com.gitee.wsl.compose.ext.text.getLineForOffsetInBounds
import com.gitee.wsl.compose.ui.richtext.content.ParagraphLayoutInfo
import com.gitee.wsl.compose.ui.richtext.content.RichTextString
import com.gitee.wsl.compose.ui.richtext.content.isDrawerOnly

/**
 * Renders the leading margins for paragraphs that have been styled
 * in the specified [ContentAnnotatedString].
 *
 * @param text the specified [ContentAnnotatedString]
 * @param layoutResult the text layout result received in onTextLayout
 */
fun Modifier.annotatedTextParagraphContents(
    text: RichTextString,
    layoutResult: MutableState<TextLayoutResult?>
): Modifier {
    return drawBehind {
        layoutResult.value?.let { layoutResult ->
            text.paragraphContents.forEach { content ->
                val startLine = layoutResult.getLineForOffsetInBounds(
                    offset = content.start,
                    checkIfDelimited = true
                )
                if (startLine < 0) {
                    // Paragraph delimited by maxLines,
                    // ignore the content of the next paragraphs
                    return@drawBehind
                }

                if (content.drawer != null && (content.isDrawerOnly() || layoutResult.getLineStart(startLine) == content.start)) {
                    val firstEndLine = layoutResult.getLineForOffsetInBounds(
                        offset = content.end - 1
                    )
                    val endOffset = layoutResult.getLineEnd(firstEndLine)
                    val endLine = if (endOffset == content.end) {
                        val nextEndLine = layoutResult.getLineForOffsetInBounds(
                            offset = content.end
                        )
                        if (nextEndLine - firstEndLine > 1) {
                            nextEndLine - 1
                        } else {
                            firstEndLine
                        }
                    } else {
                        firstEndLine
                    }

                    val dir = try {
                        layoutResult.getParagraphDirection(content.start)
                    } catch (ignore: Exception) {
                        return@drawBehind
                    }
                    content.drawer.onDraw(
                        this@drawBehind,
                        ParagraphLayoutInfo(
                            result = layoutResult,
                            startLine = startLine,
                            endLine = endLine,
                            x = if (dir == ResolvedTextDirection.Ltr) {
                                layoutResult.getLineLeft(startLine)
                            } else {
                                layoutResult.getLineRight(startLine)
                            },
                            top = layoutResult.getLineTop(startLine),
                            bottom = layoutResult.getLineBottom(endLine),
                            direction = dir
                        )
                    )
                }
            }
        }
    }
}